package space.edge.d.demo.qrcode.codescanner.scanner;


import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;

import space.edge.d.demo.qrcode.common.BinaryBitmap;
import space.edge.d.demo.qrcode.common.Result;
import space.edge.d.demo.qrcode.R;
import space.edge.d.demo.qrcode.imageproc.binarizer.HybridBinarizer;
import space.edge.d.demo.qrcode.imageproc.luminance.PlanarYUVLuminanceSource;

import java.util.concurrent.CountDownLatch;

/**
 * Created by gsl on 2017/10/30.
 * 解码一帧图像的handler
 */

public class DecodeHandler extends Handler {

    private final String TAG = DecodeHandler.class.getSimpleName();

    private PreviewHandler handler;
    private QRCodeReaderThread qrCodeReaderThread;
    private PrivateCodeReaderThread pCodeReaderThread;
    private CountDownLatch latch;
    private boolean codeReaderThreadStarted;
    private final Object lockObject;
    private boolean running = true;

    private long i;

    DecodeHandler(PreviewHandler handler) {
        i = System.currentTimeMillis();
        this.handler = handler;
        lockObject = new Object();
        qrCodeReaderThread = new QRCodeReaderThread(lockObject);
        pCodeReaderThread = new PrivateCodeReaderThread(lockObject);
    }

    private void newLatch() {
        latch = new CountDownLatch(2);
    }

    @Override
    public void handleMessage(Message msg) {
        if (msg == null || !running)
            return;
        switch (msg.what) {
            case R.id.decode:
                byte[] bytes = (byte[]) msg.obj;
                int resolutionX = msg.arg1;
                int resolutionY = msg.arg2;
                Log.d(TAG, "Current Time : " + System.currentTimeMillis() + " , time dif : " + (System.currentTimeMillis() - i));
                i = System.currentTimeMillis();
                decode(bytes, resolutionX, resolutionY);
                break;
            case R.id.quit:
                running = false;
                quit();
                Looper looper = Looper.myLooper();
                if (looper != null)
                    looper.quit();
                break;
        }
    }

    private void decode(byte[] data, int width, int height) {
        PlanarYUVLuminanceSource source = buildLuminanceSource(data, width, height);
        if (source != null) {
            BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
            newLatch();
            pCodeReaderThread.reset(latch, bitmap);
            qrCodeReaderThread.reset(latch, bitmap);
            if (!codeReaderThreadStarted) {
                pCodeReaderThread.start();
                qrCodeReaderThread.start();
                codeReaderThreadStarted = true;
            } else {
                synchronized (lockObject) {
                    lockObject.notifyAll();
                }
            }
            try {
                latch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (!running)
                return;
            Result rawResult = qrCodeReaderThread.getResult();
            if (rawResult == null)
                rawResult = pCodeReaderThread.getResult();
            if (rawResult != null) {
                Message msg = Message.obtain(handler, R.id.decode_succeeded, rawResult);
                msg.sendToTarget();
                return;
            }
            if (handler != null) {
                Message msg = Message.obtain(handler, R.id.decode_failed);
                msg.sendToTarget();
            }
        }
    }

    private PlanarYUVLuminanceSource buildLuminanceSource(byte[] data, int width, int height) {
        return handler.getCameraManager().buildLuminanceSource(data,width,height);
    }

    private void quit() {
        if (qrCodeReaderThread != null)
            qrCodeReaderThread.quit();
        if (pCodeReaderThread != null)
            pCodeReaderThread.quit();
        synchronized (lockObject) {
            lockObject.notifyAll();
        }
    }
}
